package agentFramework.core;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import agentFramework.agent.Agent;
import agentFramework.core.env.Environment;
import agentFramework.utils.Debug;


public class MessageDispatcher extends Thread 
{
	private Environment			environment;
	private Queue<Message>		messageQueue;
	private Lock				lock;
	
	
	// constructor
	public MessageDispatcher(Environment env)
	{
		this.environment = env;
		this.lock = new ReentrantLock();
		this.messageQueue = new LinkedList<Message>();
	}

	
	// adds the given message in the dispatcher's queue
	// usually used by the sender 
	public void addMessage(Message msg)
	{
		lock.lock();
		messageQueue.add(msg.clone());
		lock.unlock();
	}
	
	
	// delivers the message in the appropriate message queue
	private void dispatchMessage(Message msg)
	{
		if (msg.receiverID == Core.id)
		{
			environment.getCore().addMessage(msg);
		}
		else
		{
			Agent a = environment.getAgentById(msg.receiverID);
			
			if (a != null)
			{
				a.addMessage(msg);
			}
		}
	}
	
	
	// dispatcher's main loop
	public void run()
	{
		while (true)
		{
			if (this.environment.getCore().isAlive() == false)
			{
				/* stop this thread */
				break;
			}
			
			Message msg = null;
			
			lock.lock();
			
			if (!messageQueue.isEmpty())
			{
				msg = messageQueue.poll();
			}
			
			lock.unlock();
			
			if (msg != null)
			{
				dispatchMessage(msg);
			}
		}
	}
}
